﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace CMS.Controls
{
    public class FormBase : Panel
    {

        #region 内部类

        /// <summary>
        /// 列定义
        /// </summary>
        public class ColumnDefinition : ICloneable
        {
            /// <summary>
            /// 内边距
            /// </summary>
            public Padding Padding;

            /// <summary>
            /// 布局组件内的对齐方式
            /// </summary>
            public HorizontalAlignment Alignment;

            /// <summary>
            /// 是否填充整个单元格(除去内边距)
            /// </summary>
            public bool Fill;

            /// <summary>
            /// 列的宽度
            /// </summary>
            public int Width;

            public object Clone()
            {
                return new ColumnDefinition()
                {
                    Padding = Padding,
                    Fill = Fill,
                    Alignment = Alignment,
                    Width = Width
                };
            }
        }

        /// <summary>
        /// 布局详细信息
        /// </summary>
        public struct LayoutDetial
        {
            /// <summary>
            /// 所有列的定义
            /// </summary>
            public ColumnDefinition[] Columns;

            /// <summary>
            /// 每一行的高度
            /// </summary>
            public int RowHeight;

            /// <summary>
            /// 验证布局的时候有效
            /// </summary>
            public bool IsEmpty => RowHeight == 0 && Columns == null;
        }

        /// <summary>
        /// 行的数据信息
        /// </summary>
        protected struct RowDetial
        {
            /// <summary>
            /// 当前行的每一个位置的元素的控件
            /// </summary>
            public Control[] Controls;

            /// <summary>
            /// 当前行的特殊列定义写在此处
            /// </summary>
            public ColumnDefinition[] ColumnDefinitions;  //允许为每一个单元格定义不同的参数

            /// <summary>
            /// 额外的空间
            /// </summary>
            public object Tag;
        }

        #endregion

        #region 内部字段
        /// <summary>
        /// 保存布局信息
        /// </summary>
        private LayoutDetial _LayoutD;

        /// <summary>
        /// 保存每一行的信息
        /// </summary>
        private readonly List<RowDetial> _Rows = new List<RowDetial>();

        /// <summary>
        /// 用于遍历每一行的信息
        /// </summary>
        protected IEnumerable<RowDetial> Rows => _Rows;
        #endregion

        #region 公共属性
        /// <summary>
        /// 当没有指定列的信息时采用的默认列配置
        /// </summary>
        public static readonly ColumnDefinition DefaultColumnLayoutParam = new ColumnDefinition()
        {
            Alignment = HorizontalAlignment.Center,
            Fill = true,
            Padding = new Padding(5)
        };

        /// <summary>
        /// 设置新的布局信息
        /// </summary>
        public LayoutDetial LayoutD
        {
            get => new LayoutDetial()
            {
                Columns = (ColumnDefinition[])_LayoutD.Columns.Clone(),
                RowHeight = _LayoutD.RowHeight
            };
            set
            {
                _LayoutD = value;
                Width = Math.Max((from i in _LayoutD.Columns select i.Width).Sum(), Width);
                PerformLayout();
            }
        }

        #endregion

        public FormBase()
        {

        }

        protected void AddRow(RowDetial detail)
        {
            _Rows.Add(detail);
            Controls.AddRange(detail.Controls);
        }


        protected override void OnLayout(LayoutEventArgs levent)
        {
            if (!LayoutD.IsEmpty)
            {
                int y = 0;
                for (int i = 0; i < _Rows.Count; i++)
                {
                    RowDetial row = _Rows[i];
                    ColumnDefinition[] rowLayout = row.ColumnDefinitions ?? LayoutD.Columns;
                    int x = 0;
                    for (int j = 0; j < row.Controls.Length; j++)
                    {
                        ColumnDefinition cellLayout = rowLayout?[j] ?? LayoutD.Columns[j] ?? DefaultColumnLayoutParam;
                        if (row.Controls[j] == null)
                        {
                            x += cellLayout.Width;
                            continue;
                        }

                        Control control = row.Controls[j];
                        Padding padding = cellLayout.Padding;
                        if (cellLayout.Fill)
                        {
                            Size targetSize = new Size(cellLayout.Width - padding.Left - padding.Right, LayoutD.RowHeight - padding.Top - padding.Bottom);
                            control.Size = targetSize;
                            if (Equals(control.Size, targetSize))
                            {
                                //达到目标大小
                                control.Location = new Point(x + padding.Left, y + padding.Top);
                                x += cellLayout.Width;
                                continue;
                            }
                        }

                        switch (cellLayout.Alignment)
                        {
                            case HorizontalAlignment.Left:
                                control.Location = new Point(x + padding.Left, y + (LayoutD.RowHeight - control.Height) / 2);
                                break;
                            case HorizontalAlignment.Right:
                                control.Location = new Point(x + cellLayout.Width - control.Width - padding.Right, y + (LayoutD.RowHeight - control.Height) / 2);
                                break;
                            case HorizontalAlignment.Center:
                                control.Location = new Point(x + (cellLayout.Width - control.Width) / 2, y + (LayoutD.RowHeight - control.Height) / 2);
                                break;
                            default:
                                break;
                        }

                        x += cellLayout.Width;
                    }
                    y += LayoutD.RowHeight;
                }
            }
            //base.OnLayout(levent);
        }
    }
}
